home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 104 / MacAddict_104_2005-04.iso / Software / Internet & Communication / WordPress 1.2.2 freeware.dmg / wordpress / wp-includes / gettext.php < prev    next >
Encoding:
PHP Script  |  2004-04-16  |  6.3 KB  |  232 lines

  1. <?php
  2. /*
  3.    Copyright (c) 2003 Danilo Segan <danilo@kvota.net>.
  4.  
  5.    This file is part of PHP-gettext.
  6.  
  7.    PHP-gettext is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.  
  12.    PHP-gettext is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with PHP-gettext; if not, write to the Free Software
  19.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21. */
  22.  
  23.  
  24.  
  25.   // For start, we only want to read the MO files
  26.  
  27. class gettext_reader {
  28. //public:
  29.   var $error = 0; // public variable that holds error code (0 if no error)
  30. //private:
  31.   var $BYTEORDER = 0;
  32.   var $STREAM = NULL;
  33.   var $short_circuit = false;
  34.  
  35.   function readint() {
  36.     // Reads 4 byte value from $FD and puts it in int
  37.     // $BYTEORDER specifies the byte order: 0 low endian, 1 big endian
  38.     for ($i=0; $i<4; $i++) {
  39.       $byte[$i]=ord($this->STREAM->read(1));
  40.     }
  41.     //print sprintf("pos: %d\n",$this->STREAM->currentpos());
  42.     if ($this->BYTEORDER == 0) 
  43.       return (int)(($byte[0]) | ($byte[1]<<8) | ($byte[2]<<16) | ($byte[3]<<24));
  44.     else 
  45.       return (int)(($byte[3]) | ($byte[2]<<8) | ($byte[1]<<16) | ($byte[0]<<24));
  46.   }
  47.  
  48.   // constructor that requires StreamReader object
  49.   function gettext_reader($Reader) {
  50.     // If there isn't a StreamReader, turn on short circuit mode.
  51.     if (! $Reader) {
  52.         $this->short_circuit = true;
  53.         return;
  54.     }
  55.  
  56.     $MAGIC1 = (int)0x950412de;
  57.     $MAGIC2 = (int)0xde120495;
  58.  
  59.  
  60.     $this->STREAM = $Reader;
  61.     $magic = $this->readint();
  62.     if ($magic == $MAGIC1) {
  63.       $this->BYTEORDER = 0;
  64.     } elseif ($magic == $MAGIC2) {
  65.       $this->BYTEORDER = 1;
  66.     } else {
  67.       $this->error = 1; // not MO file
  68.       return false;
  69.     }
  70.  
  71.     // FIXME: Do we care about revision? We should.
  72.     $revision = $this->readint();
  73.  
  74.     $total = $this->readint();
  75.     $originals = $this->readint();
  76.     $translations = $this->readint();
  77.  
  78.     $this->total = $total;
  79.     $this->originals = $originals;
  80.     $this->translations = $translations;
  81.  
  82.   }
  83.  
  84.   function load_tables($translations=false) {
  85.     // if tables are loaded do not load them again
  86.     if (!is_array($this->ORIGINALS)) {
  87.       $this->ORIGINALS = array();
  88.       $this->STREAM->seekto($this->originals);
  89.       for ($i=0; $i<$this->total; $i++) {
  90.     $len = $this->readint();
  91.     $ofs = $this->readint();
  92.     $this->ORIGINALS[] = array($len,$ofs);
  93.       }
  94.     }
  95.  
  96.     // similar for translations
  97.     if ($translations and !is_array($this->TRANSLATIONS)) {
  98.       $this->TRANSLATIONS = array();
  99.       $this->STREAM->seekto($this->translations);
  100.       for ($i=0; $i<$this->total; $i++) {
  101.     $len = $this->readint();
  102.     $ofs = $this->readint();
  103.     $this->TRANSLATIONS[] = array($len,$ofs);
  104.       }
  105.     }
  106.  
  107.   }
  108.  
  109.   function get_string_number($num) {
  110.     // get a string with particular number
  111.     // TODO: Add simple hashing [check array, add if not already there]
  112.     $this->load_tables();
  113.     $meta = $this->ORIGINALS[$num];
  114.     $length = $meta[0];
  115.     $offset = $meta[1];
  116.     $this->STREAM->seekto($offset);
  117.     $data = $this->STREAM->read($length);
  118.     return (string)$data;
  119.   }
  120.  
  121.   function get_translation_number($num) {
  122.     // get a string with particular number
  123.     // TODO: Add simple hashing [check array, add if not already there]
  124.     $this->load_tables(true);
  125.     $meta = $this->TRANSLATIONS[$num];
  126.     $length = $meta[0];
  127.     $offset = $meta[1];
  128.     $this->STREAM->seekto($offset);
  129.     $data = $this->STREAM->read($length);
  130.     return (string)$data;
  131.   }
  132.   
  133.   // binary search for string
  134.   function find_string($string, $start,$end) {
  135.     //print "start: $start, end: $end\n";
  136.     if (abs($start-$end)<=1) {
  137.       // we're done, if it's not it, bye bye
  138.       $txt = $this->get_string_number($start);
  139.       if ($string == $txt)
  140.     return $start;
  141.       else
  142.     return -1;
  143.     } elseif ($start>$end) {
  144.       return $this->find_string($string,$end,$start);
  145.     }  else {
  146.       $half = (int)(($start+$end)/2);
  147.       $tst = $this->get_string_number($half);
  148.       $cmp = strcmp($string,$tst);
  149.       if ($cmp == 0) 
  150.     return $half;
  151.       elseif ($cmp<0) 
  152.     return $this->find_string($string,$start,$half);
  153.       else
  154.     return $this->find_string($string,$half,$end);
  155.     }
  156.   }
  157.  
  158.   function translate($string) {
  159.     if ($this->short_circuit) {
  160.         return $string;
  161.     }
  162.  
  163.     $num = $this->find_string($string, 0, $this->total);
  164.     if ($num == -1)
  165.       return $string;
  166.     else 
  167.       return $this->get_translation_number($num);
  168.   }
  169.  
  170.   function get_plural_forms() {
  171.     // lets assume message number 0 is header
  172.     // this is true, right?
  173.  
  174.     // cache header field for plural forms
  175.     if (is_string($this->pluralheader)) 
  176.       return $this->pluralheader;
  177.     else {
  178.       $header = $this->get_translation_number(0);
  179.  
  180.       if (eregi("plural-forms: (.*)\n",$header,$regs)) {
  181.     $expr = $regs[1];
  182.       } else {
  183.     $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
  184.       }
  185.       $this->pluralheader = $expr;
  186.       return $expr;
  187.     }
  188.   }
  189.  
  190.   function select_string($n) {
  191.     $string = $this->get_plural_forms();
  192.     $string = str_replace('nplurals',"\$total",$string);
  193.     $string = str_replace("n",$n,$string);
  194.     $string = str_replace('plural',"\$plural",$string);
  195.  
  196.     $total = 0;
  197.     $plural = 0;
  198.  
  199.     eval("$string");
  200.     if ($plural>=$total) $plural = 0;
  201.     return $plural;
  202.   }
  203.  
  204.   function ngettext($single, $plural, $number) {
  205.     if ($this->short_circuit) {
  206.       if ($number != 1) return $plural;
  207.       else return $single;
  208.     }
  209.  
  210.     // find out the appropriate form
  211.     $select = $this->select_string($number); 
  212.     
  213.  
  214.     // this should contains all strings separated by NULLs
  215.     $result = $this->find_string($single.chr(0).$plural,0,$this->total);
  216.     if ($result == -1) {
  217.       if ($number != 1) return $plural;
  218.       else return $single;
  219.     } else {
  220.       $result = $this->get_translation_number($result);
  221.     
  222.       // lets try to parse all the NUL staff
  223.       //$result = "proba0".chr(0)."proba1".chr(0)."proba2";
  224.       $list = explode (chr(0), $result);
  225.       return $list[$select];
  226.     }
  227.   }
  228.  
  229. }
  230.  
  231.  
  232. ?>